package com.buddy.java.thread.example;

import com.buddy.java.thread.guarded_suspension.Blocker;
import com.buddy.java.thread.guarded_suspension.ConditionVarBlocker;
import com.buddy.java.thread.guarded_suspension.GuardedAction;
import com.buddy.java.thread.guarded_suspension.Predicate;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;

/**
 * 借用guarded_suspension模式
 *嵌套监视器锁死示例
 */
public class NestedMonitorLockoutExample {


    public static void main(String[] args){
        final Helper helper = new Helper();
        System.out.println("Before calling guaredMethod.");
        Thread t = new Thread(new Runnable() {
            public void run() {
                String result;
                result = helper.xGuardedMethod("test");
                System.out.println(result);
            }
        });
        t.start();

        final Timer timer = new Timer(false);

        //延迟50s调用helper.stateChanged()方法
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                helper.xStateChanged();
                timer.cancel();
            }
        },50,10);
    }

    private static class Helper {

        public volatile boolean isStateOK = false;

        private final Predicate stateBeOK = new Predicate() {
            public boolean evaluate() {
                return isStateOK;
            }
        };

        private final Blocker blocker = new ConditionVarBlocker();


        public synchronized String xGuardedMethod(final String message) {
            GuardedAction<String> guardedAction = new GuardedAction<String>(stateBeOK) {
                public String call() throws Exception {
                    return message + "-> received.";
                }
            };
            String result = null;
            try {
                result = blocker.callWithGurad(guardedAction);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }

        public synchronized void xStateChanged() {
            try {
                blocker.singalAfter(new Callable<Boolean>() {
                    public Boolean call() throws Exception {
                        isStateOK = true;
                        System.out.println("state ok.");
                        return Boolean.TRUE;
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
